package com.skyolder.milkbee.web.rest;

import java.net.URI;
import java.net.URISyntaxException;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.codahale.metrics.annotation.Timed;
import com.skyolder.milkbee.domain.Card;
import com.skyolder.milkbee.domain.Leaguer;
import com.skyolder.milkbee.domain.Moderator;
import com.skyolder.milkbee.domain.Stranger;
import com.skyolder.milkbee.domain.User;
import com.skyolder.milkbee.dto.SimpleResult;
import com.skyolder.milkbee.security.AuthoritiesConstants;
import com.skyolder.milkbee.security.SecurityUtils;
import com.skyolder.milkbee.service.CardService;
import com.skyolder.milkbee.service.LeaguerService;
import com.skyolder.milkbee.service.ModeratorService;
import com.skyolder.milkbee.service.StrangerService;
import com.skyolder.milkbee.service.UserService;
import com.skyolder.milkbee.web.rest.util.HeaderUtil;
import com.skyolder.milkbee.web.rest.util.PaginationUtil;

import io.swagger.annotations.ApiParam;

/**
 * REST controller for managing Leaguer.
 */
@RestController
@RequestMapping("/api")
public class LeaguerResource {

	private final Logger log = LoggerFactory.getLogger(LeaguerResource.class);

	@Inject
	private LeaguerService leaguerService;
	@Inject
	private UserService userService;
	@Inject
	private ModeratorService moderatorService;
	@Inject
	private StrangerService strangerService;
	@Inject
	private CardService cardService;

	/**
	 * POST /leaguers : Create a new leaguer.
	 *
	 * @param leaguer
	 *            the leaguer to create
	 * @return the ResponseEntity with status 201 (Created) and with body the
	 *         new leaguer, or with status 400 (Bad Request) if the leaguer has
	 *         already an ID
	 * @throws URISyntaxException
	 *             if the Location URI syntax is incorrect
	 */
	@PostMapping("/leaguers")
	@Timed
	public ResponseEntity<Leaguer> createLeaguer(@RequestBody Leaguer leaguer) throws URISyntaxException {
		log.debug("REST request to save Leaguer : {}", leaguer);
		if (leaguer.getId() != null) {
			return ResponseEntity.badRequest().headers(
					HeaderUtil.createFailureAlert("leaguer", "idexists", "A new leaguer cannot already have an ID"))
					.body(null);
		}
		Leaguer result = leaguerService.save(leaguer);
		return ResponseEntity.created(new URI("/api/leaguers/" + result.getId()))
				.headers(HeaderUtil.createEntityCreationAlert("leaguer", result.getId().toString())).body(result);
	}

	/**
	 * PUT /leaguers : Updates an existing leaguer.
	 *
	 * @param leaguer
	 *            the leaguer to update
	 * @return the ResponseEntity with status 200 (OK) and with body the updated
	 *         leaguer, or with status 400 (Bad Request) if the leaguer is not
	 *         valid, or with status 500 (Internal Server Error) if the leaguer
	 *         couldnt be updated
	 * @throws URISyntaxException
	 *             if the Location URI syntax is incorrect
	 */
	@PutMapping("/leaguers")
	@Timed
	public ResponseEntity<Leaguer> updateLeaguer(@RequestBody Leaguer leaguer) throws URISyntaxException {
		log.debug("REST request to update Leaguer : {}", leaguer);
		if (leaguer.getId() == null) {
			return createLeaguer(leaguer);
		}
		Leaguer result = leaguerService.save(leaguer);
		return ResponseEntity.ok().headers(HeaderUtil.createEntityUpdateAlert("leaguer", leaguer.getId().toString()))
				.body(result);
	}

	/**
	 * GET /leaguers : get all the leaguers.
	 *
	 * @param pageable
	 *            the pagination information
	 * @return the ResponseEntity with status 200 (OK) and the list of leaguers
	 *         in body
	 * @throws URISyntaxException
	 *             if there is an error to generate the pagination HTTP headers
	 */
	@GetMapping("/leaguers")
	@Timed
	public ResponseEntity<List<Leaguer>> getAllLeaguers(@ApiParam(required = false) Integer stat,
			@ApiParam Pageable pageable) throws URISyntaxException {
		log.debug("REST request to get a page of Leaguers");
		Page<Leaguer> page = null;
		if (stat == null) {
			stat = 1;
		}
		switch (stat) {
		case 1: {
			page = leaguerService.queryApply(pageable);
		}
			break;
		case 2: {
			page = leaguerService.queryNoReal(pageable);
		}
			break;
		case 3: {
			page = leaguerService.queryReal(pageable);
		}
			break;
		case 4: {
			page = leaguerService.queryForbidden(pageable);
		}
			break;
		default: {
			page = leaguerService.queryReport(pageable);
		}
		}

		HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/leaguers");
		return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
	}

	@GetMapping("/allleaguers")
	@Timed
	public ResponseEntity<List<Leaguer>> getAllLeaguers4AdminSelect() throws URISyntaxException {
		if (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) {
			return ResponseEntity.badRequest()
					.headers(HeaderUtil.createFailureAlert("leaguer", "no Authorities", "you do not have Authorities"))
					.body(null);
		}
		List<Leaguer> list = leaguerService.findAll();
		return new ResponseEntity<>(list, HttpStatus.OK);
	}

	/**
	 * GET /leaguers/:id : get the "id" leaguer.
	 *
	 * @param id
	 *            the id of the leaguer to retrieve
	 * @return the ResponseEntity with status 200 (OK) and with body the
	 *         leaguer, or with status 404 (Not Found)
	 */
	@GetMapping("/leaguers/{id}")
	@Timed
	public ResponseEntity<Leaguer> getLeaguer(@PathVariable Long id) {
		log.debug("REST request to get Leaguer : {}", id);
		Leaguer leaguer = leaguerService.findOne(id);
		return Optional.ofNullable(leaguer).map(result -> new ResponseEntity<>(result, HttpStatus.OK))
				.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
	}

	/**
	 * DELETE /leaguers/:id : delete the "id" leaguer.
	 *
	 * @param id
	 *            the id of the leaguer to delete
	 * @return the ResponseEntity with status 200 (OK)
	 */
	@DeleteMapping("/leaguers/{id}")
	@Timed
	public ResponseEntity<Void> deleteLeaguer(@PathVariable Long id) {
		log.debug("REST request to delete Leaguer : {}", id);
		leaguerService.delete(id);
		return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert("leaguer", id.toString())).build();
	}

	@GetMapping("/leaguer/forbidden/{id}")
	@Timed
	public ResponseEntity<SimpleResult> forbidden(@PathVariable Long id) {
		if (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) {
			return ResponseEntity.badRequest()
					.headers(HeaderUtil.createFailureAlert("leaguer", "no Authorities", "you do not have Authorities"))
					.body(null);
		}
		Leaguer leaguer = leaguerService.findOne(id);
		leaguer.setForbidden(true);
		leaguer.setForbiddenDate(ZonedDateTime.now().plusDays(30));
		leaguerService.save(leaguer);
		SimpleResult sr = new SimpleResult(true);
		return new ResponseEntity<>(sr, HttpStatus.OK);
	}

	@GetMapping("/leaguer/forbiddenmessage/{id}")
	@Timed
	public ResponseEntity<SimpleResult> forbiddenMessage(@PathVariable Long id) {
		if (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) {
			return ResponseEntity.badRequest()
					.headers(HeaderUtil.createFailureAlert("leaguer", "no Authorities", "you do not have Authorities"))
					.body(null);
		}
		Leaguer leaguer = leaguerService.findOne(id);
		leaguer.setForbiddenMessage(true);
		leaguerService.save(leaguer);
		SimpleResult sr = new SimpleResult(true);
		return new ResponseEntity<>(sr, HttpStatus.OK);
	}

	@GetMapping("/leaguer/authentication/{id}")
	@Timed
	public ResponseEntity<SimpleResult> authentication(@PathVariable Long id) {
		if (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) {
			return ResponseEntity.badRequest()
					.headers(HeaderUtil.createFailureAlert("leaguer", "no Authorities", "you do not have Authorities"))
					.body(null);
		}
		Leaguer leaguer = leaguerService.findOne(id);
		leaguer.setAuthentication(true);
		leaguerService.save(leaguer);
		SimpleResult sr = new SimpleResult(true);
		return new ResponseEntity<>(sr, HttpStatus.OK);
	}

	@GetMapping("/modleaguer")
	@Timed
	public ResponseEntity<List<Leaguer>> getAllStrangerModLeaguers(@ApiParam Pageable pageable)
			throws URISyntaxException {
		log.debug("REST request to get a page of Categories");
		Optional<User> ouser = userService.getUserWithAuthoritiesByLogin(SecurityUtils.getCurrentUserLogin());
		User user = ouser.get();
		Long userId = user.getId();
		List<Moderator> moderators = moderatorService.findByUserId(userId);
		List<Long> categoryIds = new ArrayList<Long>();
		for (Moderator m : moderators) {
			categoryIds.add(m.getCategoryId());
		}
		List<Stranger> strangers = strangerService.doQueryByCategoryId(categoryIds);
		List<Long> ids = new ArrayList<Long>();
		if (strangers == null || strangers.isEmpty()) {
			ids.add(-1L);
		}
		for (Stranger s : strangers) {
			ids.add(s.getLeaguerId());
		}
		Page<Leaguer> page = leaguerService.doQueryByIds(ids, pageable);
		HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/modleaguer");
		return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
	}

	@PutMapping("/leaguer/monitor/{id}")
	@Timed
	@Secured(AuthoritiesConstants.ADMIN)
	public ResponseEntity<SimpleResult> monitor(@PathVariable Long id) {
		Leaguer leaguer = leaguerService.findOne(id);
		leaguer.setMonitor(true);
		leaguerService.save(leaguer);
		SimpleResult sr = new SimpleResult(true);
		return new ResponseEntity<>(sr, HttpStatus.OK);
	}

	@PutMapping("/leaguer/forbidden/bycard/{cardId}")
	@Timed
	public ResponseEntity<SimpleResult> forbiddenByCard(@PathVariable Long cardId) {

		SimpleResult sr = new SimpleResult(false);
		Optional<User> ouser = userService.getUserWithAuthoritiesByLogin(SecurityUtils.getCurrentUserLogin());
		User user = ouser.get();
		Leaguer leaguer = leaguerService.findByUser(user);
		Long uid = user.getId();
		List<Moderator> moderators = moderatorService.findByUserId(uid);
		Card card = cardService.findOne(cardId);
		card.getLeaguerId();
		boolean isModerator = false;
		for (Moderator m : moderators) {
			if (m.getCategoryId() == card.getCategoryId()) {
				isModerator = true;
				break;
			}
		}
		if (!isModerator) {
			return new ResponseEntity<>(sr, HttpStatus.FORBIDDEN);
		}
		List list = strangerService.findByCategoryIdAndLeaguerIdAndForbiddenTrue(card.getCategoryId(),
				card.getLeaguerId());
		if (list != null && list.size() > 0) {
			return new ResponseEntity<>(sr, HttpStatus.BAD_REQUEST);
		}
		Stranger stranger = new Stranger();
		stranger.setCategoryId(card.getCategoryId());
		stranger.setCreatedAt(ZonedDateTime.now());
		stranger.setCreator(user.getLogin());
		stranger.setForbidden(true);
		stranger.setInvalidAt(null);

		stranger.setInvalidLeaguerId(null);
		stranger.setInvalidUserId(null);

		stranger.setLeaguerId(card.getLeaguerId());
		stranger.setUserId(card.getUserId());

		stranger.setModeratorLeaguerId(leaguer.getId());
		stranger.setModeratorUserId(leaguer.getUserId());
		strangerService.save(stranger);
		return new ResponseEntity<>(sr, HttpStatus.OK);
	}

	@PutMapping("/leaguer/free/stranger/{strangerId}")
	@Timed
	public ResponseEntity<SimpleResult> freeStranger(@PathVariable Long strangerId) {
		SimpleResult sr = new SimpleResult(false);
		Optional<User> ouser = userService.getUserWithAuthoritiesByLogin(SecurityUtils.getCurrentUserLogin());
		User user = ouser.get();
		Leaguer leaguer = leaguerService.findByUser(user);
		Stranger stranger = strangerService.findOne(strangerId);
		List<Moderator> moderators = moderatorService.findByUserId(user.getId());
		boolean isModerator = false;
		for (Moderator m : moderators) {
			if (m.getCategoryId() == stranger.getCategoryId()) {
				isModerator = true;
				break;
			}
		}
		if (!isModerator) {
			return new ResponseEntity<>(sr, HttpStatus.FORBIDDEN);
		}
		stranger.setInvalidAt(ZonedDateTime.now());
		stranger.setInvalidLeaguerId(leaguer.getId());
		stranger.setInvalidUserId(user.getId());
		stranger.setForbidden(false);
		strangerService.save(stranger);
		sr.setSuccess(true);
		return new ResponseEntity<>(sr, HttpStatus.OK);
	}
}
